Completed
Push — master ( 7dd2d9...fd97ea )
by Thomas
49s queued 27s
created

module.exports.createZipArchive   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 4
c 3
b 0
f 0
nc 8
dl 0
loc 43
rs 8.5806
nop 3

2 Functions

Rating   Name   Duplication   Size   Complexity  
A 0 3 1
A 0 15 1
1
'use strict'
2
3
const output = require('./output')
4
const Container = require('./containers/Container')
5
const autoreload = require('./plugins/Autoreload')
6
const pkg = require('../package.json')
7
const io = require('socket.io-client')
8
const fs = require('fs')
9
const tmp = require('tmp')
10
const path = require('path')
11
const chalk = require('chalk')
12
const moment = require('moment')
13
const request = require('./util').request
14
const child = require('./util/ChildProcess')
15
const Module = require('./containers/Module')
16
const archiver = require('archiver')
17
const filesize = require('file-size')
18
19
module.exports = {
20
  uploadFile: function (containerToken, event, path, cb, spinner) {
21
    var r = request(containerToken + '/fs', {
22
      'action': event,
23
      'name': path
24
    }, {
25
      'Content-Type': 'multipart/form-data'
26
    })
27
28
    if (event === 'add' || event === 'change' || event === 'zipBall') {
29
      r = r.attach('file', path)
30
    }
31
32
    var self = this
33
    return r.end(function (response) {
34
      if (response.body && response.body === 'Error: invalid container') {
35
        Container.clean()
36
        var func = spinner || output.err
37
        func('Container ' + containerToken + ' does not exist anymore. We cleaned your local environment, so that you can start with a clean container.')
38
        process.exit()
39
      }
40
41
      autoreload(containerToken, path, event)
42
43
      if (cb) {
44
        cb(response.body || '')
45
        return
46
      }
47
      if (!response.body) {
48
        return
49
      }
50
      if (response.body.indexOf('Error:') === 0) {
51
        output.err(response.body)
52
        return
53
      }
54
      self.logSyncMessage(response.body)
55
    })
56
  },
57
58
  logMessage: function (data, ret) {
59
    var message =
60
      chalk.bold(chalk[data.color](data.component)) + ' ' +
61
      data.message
62
63
    if ('time' in data) {
64
      if (data.time === 'now') {
65
        data.time = (new Date()).getTime() / 1000
66
      }
67
      message += ' ' + chalk.dim(moment(data.time * 1000).format('hh:mm:ss'))
68
    }
69
70
    if (ret) {
71
      return message
72
    }
73
74
    return output.log(message)
75
  },
76
77
  logSyncMessage: function (message, ret, component) {
78
    return this.logMessage({
79
      component: component || 'Sync',
80
      color: 'green',
81
      message: message,
82
      time: 'now'
83
    }, !!ret)
84
  },
85
86
  createInitialZip: function (dir, containerToken, envr, cb) {
87
    var self = this
88
    this.createZipArchive(dir, 'Sync', function (zipName, size, unlinkFn) {
89
      var stopSpinner = output.wait(self.logSyncMessage('Uploading initial zipball (' + size + ')', true))
90
      try {
91
        self.uploadFile(containerToken, 'zipBall', zipName, function (responseBody) {
92
          unlinkFn()
93
          if (responseBody.indexOf('OK') !== 0) {
94
            stopSpinner(responseBody || 'Could not connect to server (empty response)')
95
            process.exit()
96
          }
97
          stopSpinner(true)
98
          cb()
99
        }, stopSpinner)
100
      } catch (e) {
101
        unlinkFn()
102
        stopSpinner(e.message)
103
      }
104
    })
105
  },
106
107
  createZipArchive: function (dir, label, cb) {
108
    if (fs.existsSync(path.join(dir, 'vendor'))) {
109
      output.warn('Ignoring directory \'vendor\'')
110
    }
111
    if (fs.existsSync(path.join(dir, 'node_modules'))) {
112
      output.warn('Ignoring directory \'node_modules\'')
113
    }
114
    if (fs.existsSync(path.join(dir, 'web/node_modules'))) {
115
      output.warn('Ignoring directory \'web/node_modules\'')
116
    }
117
118
    var zipName = tmp.tmpNameSync({})
119
    var spinner = output.wait(this.logSyncMessage('Creating zipball', true, label || 'Publish'))
120
    var zipFile = fs.createWriteStream(zipName)
121
122
    zipFile.on('close', function () {
123
      // Upload file to api.sadev.io
124
      fs.stat(zipName, function (err, stat) {
125
        if (err) {
126
          spinner('Error creating zipball')
127
          process.exit()
128
        }
129
        spinner()
130
131
        var size = filesize(stat.size).human('si')
132
        cb(zipName, size, function () {
133
          fs.unlink(zipName, function () {})
134
        })
135
      })
136
    })
137
138
    var archive = archiver('zip', {
139
      store: true
140
    })
141
    archive.on('error', function (err) {
142
      output.err(err)
143
    })
144
    archive.pipe(zipFile)
145
    archive.glob(path.join(dir, '**'), {
146
      ignore: ['.inc/**', '.git/**', 'node_modules', 'web/node_modules', 'node_modules/**', 'web/node_modules/**', 'vendor/**', '.gitignore', '.jshintrc']
147
    })
148
    archive.finalize()
149
  },
150
151
  startChildProcess: function (type, callback, basePath) {
152
    Module.getManifest(function (manifest) {
153
      // Get scripts object
154
      var scripts = manifest.getDevOption('scripts')
155
      if (!scripts || typeof scripts !== 'object' || !(type in scripts)) {
156
        return callback ? callback(0) : false
157
      }
158
159
      // Cast to array if script is string
160
      if (typeof scripts[type] === 'string') {
161
        scripts[type] = [scripts[type]]
162
      }
163
164
      if (!(type in scripts) || !('length' in scripts[type])) {
165
        return callback ? callback(0) : false
166
      }
167
168
      var count = 0
169
      for (var x in scripts[type]) {
170
        if (!scripts[type].hasOwnProperty(x)) {
171
          continue
172
        }
173
        var script = scripts[type][x]
174
        child.run(script, callback, basePath)
175
        count++
176
      }
177
178
      return !!count
179
    }, basePath)
180
  },
181
182
  startWebSocket: function (containerToken) {
183
    var socket = io('http://ws.sadev.io/')
184
    var self = this
185
186
    socket.on('connect', function () {
187
      socket.emit('room', 'SADEV:' + containerToken)
188
      socket.emit('room', 'BROADCAST')
189
      socket.emit('room', pkg.name + '/' + pkg.version)
190
      socket.emit('clientInfo', pkg)
191
    })
192
193
    socket.on('log', function (data) {
194
      if (!('color' in data)) {
195
        if (data.component === 'Logger') {
196
          data.color = 'yellow'
197
        } else {
198
          data.color = 'blue'
199
        }
200
      }
201
202
      self.logMessage(data)
203
    })
204
205
    socket.on('disconnect', function () {
206
      socket.close()
207
      setTimeout(function () {
208
        self.startWebSocket(containerToken)
209
      }, 1000)
210
    })
211
212
    socket.open()
213
  }
214
}
215